﻿using CleanToolkit.Comparison.DiffModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace CleanToolkit.Comparison.Comparers
{
    public class FieldsComparer
    {
        //****************************************************************************************
        #region Variables
        //****************************************************************************************

        /// <summary>
        /// Fichier représentant le schéma
        /// </summary>
        public string SchemaFilePath { get; set; }

        /// <summary>
        /// Fichier représentant la source de champs de référence
        /// </summary>
        public string FieldsFilePath { get; set; }

        /// <summary>
        /// Liste des comparers à appliquer
        /// </summary>
        private IList<IFieldsComparer> _comparers;

        //****************************************************************************************
        #endregion Variables
        //****************************************************************************************


        //****************************************************************************************
        #region Fonctions
        //****************************************************************************************

        /// <summary>
        /// Récupération de la liste des différences de champs pour le fichier source
        /// </summary>
        /// <returns></returns>
        public List<FieldDiffs> GetDiff()
        {
            List<FieldDiffs> result = new List<FieldDiffs>();
            //-----------------------------------------------------------------------

            // On charge les fichiers xml
            XDocument xSchema = XDocument.Load(this.SchemaFilePath);
            XDocument xFields = XDocument.Load(this.FieldsFilePath);


            // On charge la liste des champs
            IEnumerable<XElement> xSchemaFields =
                xSchema
                .Descendants(CleanConstants.CST_SpNamespace + "Fields")
                .Cast<XElement>()
                .Elements(CleanConstants.CST_SpNamespace + "Field");

            IEnumerable<XElement> xSiteFields =
                xFields
                .Descendants(CleanConstants.CST_SpNamespace + "Field");


            string spFieldId = string.Empty;

            // On compare champ par champ en partant de ceux du Schéma
            foreach (XElement xSchemaField in xSchemaFields)
            {
                // On récupère la liste des différences pour le champ xSchemaField
                FieldDiffs bufferDiffs = GetFieldDiffs(xSchemaField, xSiteFields);

                // Si la comparaison a des résultats, on la rajoute dans la liste des champs en différence remarquable
                if (bufferDiffs.Diffs.Count > 0)
                {
                    result.Add(bufferDiffs);
                }
            }


            //-----------------------------------------------------------------------
            return result;
        }

        /// <summary>
        /// Récupération de la liste des différences pour un champ
        /// </summary>
        /// <param name="xSchemaField"></param>
        /// <param name="xSiteFields"></param>
        /// <returns></returns>
        private FieldDiffs GetFieldDiffs(XElement xSchemaField, IEnumerable<XElement> xSiteFields)
        {
            // ID du SPFieldk
            string spFieldId = xSchemaField.Attribute("ID").Value;
            string spFieldName = xSchemaField.Attribute("Name").Value;
            FieldDiffs result = new FieldDiffs()
            {
                ID = spFieldId,
                Name = spFieldName
            };
            //---------------------------------------------------------------------


            // Récupération du champ équivalent
            XElement xSiteField = xSiteFields.Where(xe => xe.Attribute("ID").Value == spFieldId).FirstOrDefault();

            // Comparaison
            if (xSiteField != null)
            {
                // préparation de la structure de comparaison
                IEnumerable<FieldDiffInfo> bufferDiffs = null;

                // On itère sur les comparateurs
                foreach (IFieldsComparer comparer in _comparers)
                {
                    // Comparaison
                    bufferDiffs = comparer.Compare(xSchemaField, xSiteField);

                    // Si la comparaison retourne des résultats, on les ajoute à la structure de retour
                    if (bufferDiffs != null && bufferDiffs.Count() > 0)
                    {
                        result.Diffs.AddRange(bufferDiffs);
                    }
                }
            }
            else
            {
                // Il s'agit d'une erreur --> Remonter l'information
            }


            //---------------------------------------------------------------------
            return result;
        }
        //****************************************************************************************
        #endregion Fonctions
        //****************************************************************************************


        //****************************************************************************************
        #region Constructeurs
        //****************************************************************************************

        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        public FieldsComparer()
        {
            // Préparation de la liste des compareurs
            this._comparers = new List<IFieldsComparer>();

            // Ajout des compareurs
            this._comparers.Add(new FieldsAttributesComparer()); // Comparaison de la valeur des SPFierds
            this._comparers.Add(new FieldsFormulaComparer());    // Comparaison de la formule des SPFields
        }

        //****************************************************************************************
        #endregion Constructeurs
        //****************************************************************************************

    }
}
